package com.cw.base.jeeyc.controller;

import com.cw.base.jeeyc.api.dto.PersonDto;
import com.cw.lang.common.utils.GsonUtil;
import com.cw.lang.common.utils.IdGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * elastic person demo
 *
 * @author chenw
 * @date 2021/6/20
 */
@RestController
@RequestMapping("/elasticPerson")
@Slf4j
public class ElasticPersonController {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private static final String INDEX = "persondata";
    private static final String TYPE = "_doc";

    /**
     * insert person
     *
     */
    @RequestMapping("/insertPerson")
    public void insertPerson(PersonDto personDto) {
        personDto.setPersonId(IdGenerator.nextStrId());
        Map<String, Object> personData = new HashMap<>(2);
        personData.put("name", personDto.getName());
        personData.put("number", personDto.getNumber());
        IndexRequest indexRequest = new IndexRequest(INDEX).id(personDto.getPersonId())
            .source(personData);

        IndexResponse indexResponse;
        try {
            indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            log.info(GsonUtil.objectToJsonString(indexResponse));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //other way:json data
         // personDto.setPersonId(IdGenerator.nextStrId());
        // IndexRequest indexRequest1 = new IndexRequest(INDEX);
        // indexRequest1.id(personDto.getPersonId());
        // String jsonString = "{" + "\"name\":" + "\"" + personDto.getName() + "\"" + "}";
        // indexRequest1.source(jsonString);
        //
        // try {
        //     IndexResponse indexResponse1 = restHighLevelClient.index(indexRequest1, RequestOptions.DEFAULT);
        // } catch (IOException e) {
        //     e.printStackTrace();
        // }

    }

    @RequestMapping("/getPersonById")
    public PersonDto getPersonById(String id) {
        GetRequest getRequest = new GetRequest(INDEX, id);
        GetResponse getResponse = null;
        try {
            getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return getResponse != null ? GsonUtil.json2Obj(getResponse.getSourceAsString(), PersonDto.class) : null;
    }

    @RequestMapping("/searchAll")
    @ResponseBody
    public SearchResponse searchAll() {
        SearchRequest searchRequest = new SearchRequest(INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return searchResponse;
    }

    @RequestMapping("/updatePersonById")
    @ResponseBody
    public PersonDto updatePersonById(String id, PersonDto person) {
        // Fetch Object after its update
        UpdateRequest updateRequest = new UpdateRequest(INDEX, id).fetchSource(
            true);
        try {
            String personJson = GsonUtil.objectToJsonString(person);
            updateRequest.doc(personJson, XContentType.JSON);
            UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            return GsonUtil.json2Obj(updateResponse.getGetResult()
                .sourceAsString(), PersonDto.class);
        } catch (JsonProcessingException e) {
            e.getMessage();
        } catch (java.io.IOException e) {
            e.getLocalizedMessage();
        }
        System.out.println("Unable to update person");
        return null;
    }

    @RequestMapping("/deletePersonById")
    @ResponseBody
    public void deletePersonById(String id) {
        DeleteRequest deleteRequest = new DeleteRequest(INDEX, id);
        try {
            DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            log.info(GsonUtil.objectToJsonString(deleteResponse));
        } catch (java.io.IOException e) {
            e.getLocalizedMessage();
        }
    }

    public void test(){
        PersonDto person = new PersonDto();
        person.setName("张三");
        System.out.println("Inserting a new Person with name " + person.getName());
        person.setNumber("111111");
        insertPerson(person);
        System.out.println("Person inserted --> " + person);


        person = new PersonDto();
        person.setName("姚明");
        System.out.println("Inserting a new Person with name " + person.getName());
        person.setNumber("222222");
        insertPerson(person);
        System.out.println("Person inserted --> " + person);


        person.setName("李四");
        System.out.println("Changing name to " + person.getName());
        updatePersonById(person.getPersonId(), person);
        System.out.println("Person updated  --> " + person);


        System.out.println("Searching for all documents");
        SearchResponse response = searchAll();
        System.out.println(response);

        System.out.println("Searching for a term");
        //response = searchTerm();
        System.out.println(response);

        System.out.println("Match a query");
        //response = matchQuery();
        System.out.println(response);

        System.out.println("Getting 李四");
        PersonDto personFromDb = getPersonById(person.getPersonId());
        System.out.println("Person from DB  --> " + personFromDb);



        System.out.println("Deleting " + person.getName());
        deletePersonById(personFromDb.getPersonId());
        System.out.println("Person " + person.getName() + " deleted!");
    }
}
